package com.sky.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.sky.dto.DocumentPageQueryDTO;
import com.sky.dto.DocumentUpdateDTO;
import com.sky.dto.DocumentCategoryDTO;
import com.sky.entity.Document;
import com.sky.entity.DocumentCategory;
import com.sky.entity.DocumentDownload;
import com.sky.entity.DocumentPrint;
import com.sky.mapper.DocumentMapper;
import com.sky.mapper.DocumentCategoryMapper;
import com.sky.mapper.DocumentDownloadMapper;
import com.sky.mapper.DocumentPrintMapper;
import com.sky.service.DocumentService;
import com.sky.vo.DocumentVO;
import com.sky.vo.DocumentStatisticsVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FilenameUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.PrintWriter;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;

import com.sky.utils.DocumentConversionUtil;

@Service
@Slf4j
public class DocumentServiceImpl extends ServiceImpl<DocumentMapper, Document> implements DocumentService {

    @Autowired
    private DocumentMapper documentMapper;

    @Autowired
    private DocumentCategoryMapper documentCategoryMapper;

    @Autowired
    private DocumentDownloadMapper documentDownloadMapper;

    @Autowired
    private DocumentPrintMapper documentPrintMapper;

    // 文档存储路径
    private static final String DOCUMENT_STORAGE_PATH = "f:\\pro\\飞印\\原型8.8\\后端\\文档库\\";

    @Override
    public Page<DocumentVO> pageQuery(DocumentPageQueryDTO pageQueryDTO) {
        Page<Document> page = new Page<>(pageQueryDTO.getCurrent(), pageQueryDTO.getPageSize());
        LambdaQueryWrapper<Document> queryWrapper = new LambdaQueryWrapper<>();

        // 设置查询条件
        if (pageQueryDTO.getFileName() != null && !pageQueryDTO.getFileName().isEmpty()) {
            queryWrapper.like(Document::getFileName, pageQueryDTO.getFileName());
        }
        if (pageQueryDTO.getTitle() != null && !pageQueryDTO.getTitle().isEmpty()) {
            queryWrapper.like(Document::getTitle, pageQueryDTO.getTitle());
        }
        if (pageQueryDTO.getCategory() != null && !pageQueryDTO.getCategory().isEmpty()) {
            queryWrapper.eq(Document::getCategory, pageQueryDTO.getCategory());
        }
        if (pageQueryDTO.getIsPublic() != null) {
            queryWrapper.eq(Document::getIsPublic, pageQueryDTO.getIsPublic());
        }
        if (pageQueryDTO.getStatus() != null && !pageQueryDTO.getStatus().isEmpty()) {
            queryWrapper.eq(Document::getStatus, pageQueryDTO.getStatus());
        }
        // 默认只显示状态为私有或公开的文档，不显示待审核状态
        if (pageQueryDTO.getIsPublic() == null) {
            queryWrapper.in(Document::getIsPublic, "private", "public");
        }

        // 排序
        queryWrapper.orderByDesc(Document::getUploadTime);

        // 分页查询
        documentMapper.selectPage(page, queryWrapper);

        // 转换为VO对象
        Page<DocumentVO> resultPage = new Page<>(page.getCurrent(), page.getSize());
        resultPage.setTotal(page.getTotal());
        
        // 获取所有文档的打印次数
        List<Map<String, Object>> printCounts = documentPrintMapper.countPrintsByDocumentIds();
        Map<Integer, Integer> printCountMap = new HashMap<>();
        for (Map<String, Object> map : printCounts) {
            Integer documentId = ((Number) map.get("document_id")).intValue();
            Integer printCount = ((Number) map.get("print_count")).intValue();
            printCountMap.put(documentId, printCount);
        }
        
        List<DocumentVO> records = page.getRecords().stream().map(document -> {
            DocumentVO documentVO = new DocumentVO();
            BeanUtils.copyProperties(document, documentVO);
            // 这里可以添加上传者信息查询逻辑
            // 为了简化，这里使用默认值
            documentVO.setUploaderName("管理员");
            documentVO.setUploaderType("admin");
            
            // 设置打印次数
            documentVO.setPrintCount(printCountMap.getOrDefault(document.getId(), 0));
            
            return documentVO;
        }).collect(Collectors.toList());
        resultPage.setRecords(records);
        return resultPage;
    }

    @Override
    public DocumentVO getById(Integer id) {
        Document document = documentMapper.selectById(id);
        if (document == null) {
            return null;
        }

        DocumentVO documentVO = new DocumentVO();
        BeanUtils.copyProperties(document, documentVO);
        // 这里可以添加上传者信息查询逻辑
        documentVO.setUploaderName("管理员");
        documentVO.setUploaderType("admin");
        return documentVO;
    }

    @Override
    @Transactional
    public Integer upload(MultipartFile file, String title, String category, String isPublic) {
        // 处理文件保存
        String fileName = file.getOriginalFilename();
        String fileExtension = FilenameUtils.getExtension(fileName);
        String newFileName = generateUniqueFileName(fileName);

        // 确保存储目录存在
        File storageDir = new File(DOCUMENT_STORAGE_PATH);
        if (!storageDir.exists()) {
            storageDir.mkdirs();
        }

        // 保存文件
        try {
            File dest = new File(DOCUMENT_STORAGE_PATH + newFileName);
            file.transferTo(dest);
        } catch (IOException e) {
            log.error("文件保存失败", e);
            throw new RuntimeException("文件保存失败", e);
        }

        // 创建文档记录
        Document document = Document.builder()
                .title(title)
                .fileName(fileName)
                .filePath(DOCUMENT_STORAGE_PATH + newFileName)
                .fileSize(file.getSize())
                .fileType(file.getContentType())
                .category(category)
                .uploadBy(1) // 假设管理员ID为1
                .uploadTime(LocalDateTime.now())
                .downloadCount(0)
                .isPublic(isPublic)
                .status("active")
                .build();

        documentMapper.insert(document);
        return document.getId();
    }

    @Override
    public void update(DocumentUpdateDTO documentUpdateDTO) {
        Document document = new Document();
        BeanUtils.copyProperties(documentUpdateDTO, document);
        documentMapper.updateById(document);
    }

    @Override
    @Transactional
    public void delete(Integer id) {
        // 删除数据库记录
        Document document = documentMapper.selectById(id);
        if (document != null) {
            // 删除文件
            File file = new File(document.getFilePath());
            if (file.exists()) {
                file.delete();
            }
            // 删除数据库记录
            documentMapper.deleteById(id);
        }
    }

    @Override
    public void toggleStatus(Integer id, String status) {
        Document document = new Document();
        document.setId(id);
        document.setStatus(status);
        documentMapper.updateById(document);
    }

    @Override
    public void togglePublic(Integer id, String isPublic) {
        Document document = new Document();
        document.setId(id);
        document.setIsPublic(isPublic);
        documentMapper.updateById(document);
    }
    
    @Override
    public void reviewDocument(Integer id, String action) {
        Document document = documentMapper.selectById(id);
        if (document == null) {
            throw new RuntimeException("文档不存在");
        }
        
        // 验证审核动作
        if (!"approve".equals(action) && !"reject".equals(action)) {
            throw new RuntimeException("审核动作无效，必须是'approve'或'reject'");
        }
        
        // 更新文档状态
        Document updateDoc = new Document();
        updateDoc.setId(id);
        
        if ("approve".equals(action)) {
            // 审核通过，设置为公开
            updateDoc.setIsPublic("public");
        } else if ("reject".equals(action)) {
            // 审核拒绝，设置为私有
            updateDoc.setIsPublic("private");
        }
        
        documentMapper.updateById(updateDoc);
    }

    @Override
    @Transactional
    public void download(Integer id, HttpServletResponse response) throws IOException {
        Document document = documentMapper.selectById(id);
        if (document == null) {
            response.setStatus(HttpServletResponse.SC_NOT_FOUND);
            return;
        }

        // 更新下载次数
        document.setDownloadCount(document.getDownloadCount() + 1);
        documentMapper.updateById(document);

        // 记录下载日志
        DocumentDownload downloadRecord = DocumentDownload.builder()
                .documentId(id)
                .userId(1) // 假设当前用户ID为1
                .userType("admin")
                .downloadTime(LocalDateTime.now())
                .ipAddress("127.0.0.1")
                .build();
        documentDownloadMapper.insert(downloadRecord);

        // 设置响应头
        response.setContentType(document.getFileType());
        response.setHeader("Content-Disposition", "attachment; filename=" + 
                new String(document.getFileName().getBytes(StandardCharsets.UTF_8), "ISO-8859-1"));

        // 读取文件并输出
        try (FileInputStream fis = new FileInputStream(document.getFilePath());
             ServletOutputStream sos = response.getOutputStream()) {
            byte[] buffer = new byte[1024];
            int len;
            while ((len = fis.read(buffer)) > 0) {
                sos.write(buffer, 0, len);
            }
        }
    }

    @Override
    public void preview(Integer id, HttpServletResponse response) throws IOException {
        Document document = documentMapper.selectById(id);
        if (document == null) {
            response.setStatus(HttpServletResponse.SC_NOT_FOUND);
            return;
        }

        if (document.getStatus().equals("inactive")) {
            response.setStatus(HttpServletResponse.SC_FORBIDDEN);
            response.getWriter().write("文档已禁用，无法预览");
            return;
        }

        // 获取请求头，检查是否需要返回原始内容
        String forceRawContent = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
                .getRequest().getHeader("_forceRawContent");
        boolean isForceRawContent = "true".equals(forceRawContent);
        
        // 检查是否为打印请求
        String printParam = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes())
                .getRequest().getParameter("print");
        boolean isPrintRequest = "true".equals(printParam);

        String fileName = document.getFileName().toLowerCase();
        String filePath = document.getFilePath();

        try {
            // 检查是否需要返回原始内容
            if (isForceRawContent) {
                // 对于所有文件类型，返回原始二进制内容
                String mimeType;
                
                if (fileName.endsWith(".rtf")) {
                    mimeType = "application/rtf";
                } else if (fileName.endsWith(".txt")) {
                    mimeType = "text/plain";
                } else if (fileName.endsWith(".jpg") || fileName.endsWith(".jpeg")) {
                    mimeType = "image/jpeg";
                } else if (fileName.endsWith(".png")) {
                    mimeType = "image/png";
                } else if (fileName.endsWith(".gif")) {
                    mimeType = "image/gif";
                } else if (fileName.endsWith(".pdf")) {
                    mimeType = "application/pdf";
                } else if (fileName.endsWith(".doc")) {
                    mimeType = "application/msword";
                } else if (fileName.endsWith(".docx")) {
                    mimeType = "application/vnd.openxmlformats-officedocument.wordprocessingml.document";
                } else {
                    // 默认使用application/octet-stream
                    mimeType = "application/octet-stream";
                }
                
                response.setContentType(mimeType);
                response.setHeader("Content-Disposition", "inline; filename=" + 
                        new String(document.getFileName().getBytes(StandardCharsets.UTF_8), "ISO-8859-1"));
                
                // 读取文件并输出
                try (FileInputStream fis = new FileInputStream(filePath);
                     ServletOutputStream sos = response.getOutputStream()) {
                    byte[] buffer = new byte[1024];
                    int len;
                    while ((len = fis.read(buffer)) > 0) {
                        sos.write(buffer, 0, len);
                    }
                }
            } else {
                // 处理PDF文件 - 转换为图片
                if (fileName.endsWith(".pdf")) {
                    // 设置响应类型为HTML，用于显示图片
                    response.setContentType("text/html;charset=UTF-8");
                    response.setHeader("Content-Disposition", "inline; filename=" + 
                            new String(document.getFileName().getBytes(StandardCharsets.UTF_8), "ISO-8859-1"));
                    
                    try (PrintWriter writer = response.getWriter()) {
                        // 转换PDF为图片
                        List<String> imageBase64List = DocumentConversionUtil.convertPdfToImages(filePath);
                        
                        // 构建HTML页面显示图片
                        writer.println("<!DOCTYPE html>");
                        writer.println("<html><head><meta charset='UTF-8'><title>PDF预览</title>");
                        writer.println("<style>");
                        if (isPrintRequest) {
                            // 打印样式优化
                            writer.println("@media print {");
                            writer.println("  body {margin: 0; padding: 0; background: white;}");
                            writer.println("  img {max-width: 100%; height: auto; page-break-inside: avoid;}");
                            writer.println("}");
                            // 确保在打印对话框中预览时能正确显示
                            writer.println("body {margin: 0; padding: 20px; background: white;}");
                            writer.println("img {max-width: 100%; height: auto; display: block; margin-bottom: 10px;}");
                        } else {
                            writer.println("img {max-width: 100%; height: auto; margin-bottom: 20px;}");
                        }
                        writer.println("</style>");
                        writer.println("</head><body>");
                        
                        for (String imageBase64 : imageBase64List) {
                            writer.println("<img src='data:image/png;base64," + imageBase64 + "' alt='PDF页面'>");
                        }
                        
                        // 如果是打印请求，添加打印脚本
                        if (isPrintRequest) {
                            writer.println("<script>window.onload = function() { setTimeout(function() { window.print(); }, 1000); }</script>");
                        }
                        
                        writer.println("</body></html>");
                    }
                }
                // 处理Word文档 - 转换为HTML
                else if (fileName.endsWith(".doc") || fileName.endsWith(".docx")) {
                    response.setContentType("text/html;charset=UTF-8");
                    response.setHeader("Content-Disposition", "inline; filename=" + 
                            new String(document.getFileName().getBytes(StandardCharsets.UTF_8), "ISO-8859-1"));
                    
                    try (PrintWriter writer = response.getWriter()) {
                        // 转换Word为HTML
                        String htmlContent = DocumentConversionUtil.convertWordToHtml(filePath);
                        
                        if (isPrintRequest) {
                            // 打印模式：添加打印样式和自动打印脚本
                            StringBuilder printHtml = new StringBuilder();
                            printHtml.append("<!DOCTYPE html>");
                            printHtml.append("<html><head><meta charset='UTF-8'><title>Word预览</title>");
                            printHtml.append("<style>");
                            printHtml.append("@media print {body {margin: 0; padding: 0;}}");
                            printHtml.append("body {font-family: Arial, sans-serif; font-size: 12pt;}");
                            printHtml.append("table {border-collapse: collapse; width: 100%;}");
                            printHtml.append("th, td {border: 1px solid #ddd; padding: 4px;}");
                            printHtml.append("</style>");
                            printHtml.append("</head><body>");
                            
                            // 添加原始HTML内容
                            int bodyStart = htmlContent.indexOf("<body>");
                            int bodyEnd = htmlContent.lastIndexOf("</body>");
                            if (bodyStart > -1 && bodyEnd > -1) {
                                printHtml.append(htmlContent.substring(bodyStart + 6, bodyEnd));
                            } else {
                                printHtml.append(htmlContent);
                            }
                            
                            // 添加自动打印脚本
                            printHtml.append("<script>window.onload = function() { setTimeout(function() { window.print(); }, 1000); }</script>");
                            printHtml.append("</body></html>");
                            
                            writer.println(printHtml.toString());
                        } else {
                            // 正常预览模式
                            writer.println(htmlContent);
                        }
                    }
                }
                // 处理PPT文件 - 提供下载或简单预览
                else if (fileName.endsWith(".ppt") || fileName.endsWith(".pptx")) {
                    response.setContentType("text/html;charset=UTF-8");
                    response.setHeader("Content-Disposition", "inline; filename=" + 
                            new String(document.getFileName().getBytes(StandardCharsets.UTF_8), "ISO-8859-1"));
                    
                    try (PrintWriter writer = response.getWriter()) {
                        // 构建一个简单的HTML页面，显示PPT文件信息并提供下载链接
                        writer.println("<!DOCTYPE html>");
                        writer.println("<html><head><meta charset='UTF-8'><title>PPT预览</title></head>");
                        writer.println("<body>");
                        writer.println("<h3>PPT文件预览</h3>");
                        writer.println("<p>文件名: " + document.getFileName() + "</p>");
                        writer.println("<p>文件大小: " + (document.getFileSize() / 1024) + " KB</p>");
                        writer.println("<p>如需查看完整内容，请下载文件后使用PowerPoint或其他兼容软件打开。</p>");
                        writer.println("<a href='javascript:void(0)' onclick='window.parent.downloadFile();'>下载文件</a>");
                        writer.println("</body></html>");
                    }
                }
                // 其他文件类型 - 保持原有逻辑
                else {
                    // 设置响应头 - 使用inline而不是attachment，让浏览器尝试内联显示
                    // 根据文件扩展名设置正确的MIME类型
                    String mimeType;
                    
                    if (fileName.endsWith(".rtf")) {
                        mimeType = "application/rtf";
                    } else if (fileName.endsWith(".txt")) {
                        mimeType = "text/plain";
                    } else if (fileName.endsWith(".jpg") || fileName.endsWith(".jpeg")) {
                        mimeType = "image/jpeg";
                    } else if (fileName.endsWith(".png")) {
                        mimeType = "image/png";
                    } else if (fileName.endsWith(".gif")) {
                        mimeType = "image/gif";
                    } else {
                        // 默认使用application/octet-stream
                        mimeType = "application/octet-stream";
                    }
                    
                    response.setContentType(mimeType);
                    response.setHeader("Content-Disposition", "inline; filename=" + 
                            new String(document.getFileName().getBytes(StandardCharsets.UTF_8), "ISO-8859-1"));
                    
                    // 读取文件并输出
                    try (FileInputStream fis = new FileInputStream(filePath);
                         ServletOutputStream sos = response.getOutputStream()) {
                        byte[] buffer = new byte[1024];
                        int len;
                        while ((len = fis.read(buffer)) > 0) {
                            sos.write(buffer, 0, len);
                        }
                    }
                }
            }
        } catch (Exception e) {
            log.error("文档预览转换失败", e);
            // 转换失败时，返回错误信息
            response.setContentType("text/html;charset=UTF-8");
            try (PrintWriter writer = response.getWriter()) {
                writer.println("<!DOCTYPE html>");
                writer.println("<html><head><meta charset='UTF-8'><title>预览失败</title></head>");
                writer.println("<body><h3>文档预览转换失败</h3>");
                writer.println("<p>错误信息: " + e.getMessage() + "</p>");
                writer.println("<p>请尝试下载文档查看</p>");
                writer.println("</body></html>");
            }
        }
    }



    @Override
    public List<DocumentCategory> getCategoryList() {
        return documentCategoryMapper.selectList(null);
    }

    @Override
    public Integer addCategory(DocumentCategoryDTO categoryDTO) {
        DocumentCategory category = new DocumentCategory();
        BeanUtils.copyProperties(categoryDTO, category);
        category.setCreatedAt(LocalDateTime.now());
        category.setUpdatedAt(LocalDateTime.now());
        documentCategoryMapper.insert(category);
        return category.getId();
    }

    @Override
    public void updateCategory(Integer id, DocumentCategoryDTO categoryDTO) {
        DocumentCategory category = new DocumentCategory();
        BeanUtils.copyProperties(categoryDTO, category);
        category.setId(id);
        category.setUpdatedAt(LocalDateTime.now());
        documentCategoryMapper.updateById(category);
    }

    @Override
    public void deleteCategory(Integer id) {
        // 检查是否有文档使用该分类
        LambdaQueryWrapper<Document> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Document::getCategory, id);
        Long count = documentMapper.selectCount(queryWrapper);
        if (count > 0) {
            throw new RuntimeException("该分类下有文档，无法删除");
        }
        documentCategoryMapper.deleteById(id);
    }

    @Override
    public DocumentStatisticsVO getStatistics() {
        // 总下载次数
        Integer totalDownloads = documentMapper.sumDownloadCount();
        // 总打印次数
        Integer totalPrints = documentPrintMapper.countTotalPrints();
        // 学生上传文档数（数据库中没有uploader_type列，返回0）
        Integer studentDocs = 0;
        // 商家上传文档数（数据库中没有uploader_type列，返回0）
        Integer merchantDocs = 0;
        // 管理员上传文档数（数据库中没有uploader_type列，返回0）
        Integer adminDocs = 0;
        // 公开文档数
        Integer publicDocs = documentMapper.countByIsPublic("public");
        // 正常文档数
        Integer activeDocs = documentMapper.countByStatus("active");

        return DocumentStatisticsVO.builder()
                .totalDownloads(totalDownloads)
                .totalPrints(totalPrints)
                .studentDocs(studentDocs)
                .merchantDocs(merchantDocs)
                .adminDocs(adminDocs)
                .publicDocs(publicDocs)
                .activeDocs(activeDocs)
                .build();
    }

    /**
     * 生成唯一文件名，避免文件名重复
     * @param originalFileName 原始文件名
     * @return 唯一文件名
     */
    private String generateUniqueFileName(String originalFileName) {
        String extension = FilenameUtils.getExtension(originalFileName);
        String baseName = FilenameUtils.getBaseName(originalFileName);
        String timestamp = String.valueOf(System.currentTimeMillis());
        String uuid = UUID.randomUUID().toString().substring(0, 8);
        return baseName + "_" + timestamp + "_" + uuid + "." + extension;
    }
}